package com.sky.haikangdemo.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.sky.haikangdemo.config.PublicStartConfig;
import com.sky.haikangdemo.entity.Gate;
import com.sky.haikangdemo.entity.PlateInfo;
import com.sky.haikangdemo.hiksdk.HCNetSDK;
import com.sky.haikangdemo.utils.ApplicationContextHelper;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import tk.mybatis.mapper.util.StringUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.sky.haikangdemo.hiksdk.HCNetSDK.NET_ITS_PICTURE_INFO;

@Slf4j
public class MsgCallBackService {

//    @Autowired
//    private EnterService enterService;
//    @Autowired
//    private ExitService exitService;


    private final EnterService enterService = (EnterService) ApplicationContextHelper.getBean("enterService");

    private final ExitService exitService = (ExitService) ApplicationContextHelper.getBean("exitService");

    /**
     * 道闸控制DEMO
     *
     * @param plateInfo
     */
    public void plateInOrOut(PlateInfo plateInfo) {

        //TODO 获取本地停车场道闸设备列表
        List<Gate> gates = PublicStartConfig.gates;
        System.out.println("获取本地停车场道闸设备列表：" + gates);
        for (Gate g : gates) {
            if (String.valueOf(g.getDeviceId()).equals(plateInfo.getDeviceId())) {
                // 查看是否是出/入口设备
                if (1 == g.getCutType()) {
                    new Thread(() -> {
                        enterService.plateEnter(plateInfo, "稍后自动关闭");
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        exitService.plateOut(plateInfo, "模拟自动关闭中");
                    }).start();
                }
                if (2 == g.getCutType()) {
                    new Thread(() -> exitService.plateOut(plateInfo, "一路顺风")).start();
                }
            }
        }
    }


    public static boolean commonMsgCallBack(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        log.info("【海康车牌摄像头回调】进入回调 开始识别车牌。 回调函数类型 lCommand: 0x{}", Integer.toHexString(lCommand));
        switch (lCommand) {
            //交通抓拍结果上传
            case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:
                log.info("交通抓拍结果上传");
                break;
            // 交通抓拍的终端图片上传
            case HCNetSDK.COMM_ITS_PLATE_RESULT:
                cameraCallbackHandle(pAlarmer, pAlarmInfo);
                break;
            //报警信息主动上传
            case HCNetSDK.COMM_ALARM:
                log.info("报警信息主动上传");
                break;
            default:
                log.info("车辆授权和非授权名单数据需要同步报警上传");
                break;
        }
        return true;
    }

    /**
     * 摄像头回调处理
     */
    private static void cameraCallbackHandle(HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo) {
        log.info("【海康车牌摄像头回调】交通抓拍的终端图片上传");
        HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
        strItsPlateResult.write();
        Pointer pItsPlateInfo = strItsPlateResult.getPointer();
        pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());
        strItsPlateResult.read();
        try {
            String license = new String(strItsPlateResult.struPlateInfo.sLicense, "GBK");
            // ip地址
            String host = new String(pAlarmer.sDeviceIP).trim();
            // 车型识别：0- 未知，1- 客车(大型)，2- 货车(大型)，3- 轿车(小型)，4- 非机动车
            String type = strItsPlateResult.byVehicleType + "".trim();
            NET_ITS_PICTURE_INFO[] strPicInfo = strItsPlateResult.struPicInfo;
            byte[] byDeviceId = strItsPlateResult.byDeviceID;
            String plateNumber = license.substring(1).trim();
            String byCountry = license.substring(1, 2).trim();
            String byColor = license.substring(0, 1).trim();

            log.info("【海康车牌摄像头回调】ip地址: {}", host);
            log.info("【海康车牌摄像头回调】have图片:{},图片数量:{}", CollectionUtil.isNotEmpty(Arrays.asList(strPicInfo)), strPicInfo.length);
            log.info("【海康车牌摄像头回调】设备id: {}", new StringBuilder(new String(byDeviceId).trim()));
            log.info("【海康车牌摄像头回调】车辆类型: {}", type);
            log.info("【海康车牌摄像头回调】车牌号: {}", plateNumber);
            log.info("【海康车牌摄像头回调】车牌省份: {}", byCountry);
            log.info("【海康车牌摄像头回调】车牌颜色: {}", byColor);
            PlateInfo plateInfo = new PlateInfo();
            plateInfo.setPlate(plateNumber);
            plateInfo.setPlateType(byColor + "牌");
            plateInfo.setDeviceId(new String(byDeviceId).trim());
            plateInfo.setDeviceIP(host);
            MsgCallBackService msgCallBackService = new MsgCallBackService();
            msgCallBackService.plateInOrOut(plateInfo);
            /**
             * 报警图片保存，车牌，车辆图片
             */
            String imageDirPath = "D:\\image\\";
            picCallBack(imageDirPath, strItsPlateResult);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 抓拍PIC处理
     */
    public static void picCallBack(String imageDirPath, HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult) {
        if (StringUtil.isNotEmpty(imageDirPath)) {
            File imageDir = new File(imageDirPath);
            if (!imageDir.exists() || !imageDir.isDirectory()) {
                imageDir.mkdirs();
            }
            for (int i = 0; i < strItsPlateResult.dwPicNum; i++) {
                if (strItsPlateResult.struPicInfo[i].dwDataLen > 0) {
                    String baseName = DateUtil.format(new Date(), "yyyyMMddHHmmss");
                    String imagePath = imageDir + "\\" + i + baseName + ".jpg";
                    FileOutputStream fout;
                    try {
                        fout = new FileOutputStream(imagePath);
                        //将字节写入文件
                        long offset = 0;
                        ByteBuffer buffers = strItsPlateResult.struPicInfo[i].pBuffer.getByteBuffer(offset, strItsPlateResult.struPicInfo[i].dwDataLen);
                        byte[] bytes = new byte[strItsPlateResult.struPicInfo[i].dwDataLen];
                        buffers.rewind();
                        buffers.get(bytes);
                        fout.write(bytes);
                        fout.close();
                        // TODO 上传到云端
                        log.info("【海康车牌摄像头回调】图片保存成功: {}", imagePath);
                        log.info("开始上传到云端");

                        // TODO 图片入库（业务） ...

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
//                        // 删除临时文件 imageFile
                        File imageFile = new File(imagePath);
                        boolean delete = imageFile.delete();
                        if (delete) {
                            log.info("【海康车牌摄像头回调】临时文件删除成功: {}", imagePath);
                        }
                    }
                }
            }
        }
    }

}
